package com.ikun.kunpicturebackend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ikun.kunpicturebackend.domain.Space;
import com.ikun.kunpicturebackend.domain.SpaceUser;
import com.ikun.kunpicturebackend.domain.User;
import com.ikun.kunpicturebackend.exception.BusinessException;
import com.ikun.kunpicturebackend.exception.ErrorCode;
import com.ikun.kunpicturebackend.exception.ThrowUtils;
import com.ikun.kunpicturebackend.model.dto.spaceuser.SpaceUserAddRequest;
import com.ikun.kunpicturebackend.model.dto.spaceuser.SpaceUserQueryRequest;
import com.ikun.kunpicturebackend.model.enums.SpaceRoleEnum;
import com.ikun.kunpicturebackend.model.vo.SpaceUserVO;
import com.ikun.kunpicturebackend.model.vo.SpaceVO;
import com.ikun.kunpicturebackend.model.vo.UserVO;
import com.ikun.kunpicturebackend.service.SpaceService;
import com.ikun.kunpicturebackend.service.SpaceUserService;
import com.ikun.kunpicturebackend.mapper.SpaceUserMapper;
import com.ikun.kunpicturebackend.service.UserService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author 32144
* @description 针对表【space_user(空间用户关联)】的数据库操作Service实现
* @createDate 2025-10-27 22:21:10
*/
@Service
public class SpaceUserServiceImpl extends ServiceImpl<SpaceUserMapper, SpaceUser>
    implements SpaceUserService{

    @Resource
    private UserService userService;

    @Resource
    @Lazy
    private SpaceService spaceService;

    @Override
    public long addSpaceUser(SpaceUserAddRequest spaceUserAddRequest) {
        ThrowUtils.throwIf(spaceUserAddRequest == null, ErrorCode.PARAMS_ERROR);
        SpaceUser spaceUser = new SpaceUser();
        BeanUtil.copyProperties(spaceUserAddRequest, spaceUser);
        // 校验
        validSpaceUser(spaceUser, true);
        // 添加至数据库
        this.save(spaceUser);
        return spaceUser.getId();
    }

    @Override
    public void validSpaceUser(SpaceUser spaceUser, boolean add) {
        ThrowUtils.throwIf(spaceUser == null, ErrorCode.PARAMS_ERROR);
        Long userId = spaceUser.getUserId();
        Long spaceId = spaceUser.getSpaceId();
        if (add) {
            // 新增操作，判断该用户和空间是否存在
            ThrowUtils.throwIf(ObjUtil.hasEmpty(userId, spaceId), ErrorCode.PARAMS_ERROR);
            User user = userService.getById(userId);
            ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR, "用户不存在");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
        }
        // 校验空间角色
        String spaceRole = spaceUser.getSpaceRole();
        SpaceRoleEnum spaceRoleEnum = SpaceRoleEnum.getEnumByValue(spaceRole);
        if (spaceRole != null && spaceRoleEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间角色不存在");
        }
    }

    @Override
    public QueryWrapper<SpaceUser> getQueryWrapper(SpaceUserQueryRequest queryRequest) {
        QueryWrapper<SpaceUser> queryWrapper = new QueryWrapper<>();
        if (queryRequest == null) {
            return queryWrapper;
        }
        Long id = queryRequest.getId();
        Long userId = queryRequest.getUserId();
        Long spaceId = queryRequest.getSpaceId();
        String spaceRole = queryRequest.getSpaceRole();
        queryWrapper.eq(id != null, "id", id)
                .eq(userId != null, "userId", userId)
                .eq(spaceId != null, "spaceId", spaceId)
                .eq(StrUtil.isNotBlank(spaceRole), "spaceRole", spaceRole);
        return queryWrapper;
    }

    @Override
    public SpaceUserVO getSpaceUserVO(SpaceUser spaceUser, HttpServletRequest request) {
        SpaceUserVO spaceUserVO = SpaceUserVO.objToVO(spaceUser);
        Long userId = spaceUser.getUserId();
        if (userId != null && userId > 0){
            // 关联用户信息
            User user = userService.getById(userId);
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            spaceUserVO.setUserVO(userVO);
        }
        Long spaceId = spaceUser.getSpaceId();
        if (spaceId != null && spaceId > 0){
            // 关联空间信息
            Space space = spaceService.getById(spaceId);
            SpaceVO spaceVO = spaceService.getSpaceVO(space, request);
            spaceUserVO.setSpaceVO(spaceVO);
        }
        return spaceUserVO;
    }

    @Override
    public List<SpaceUserVO> getSpaceUserVOList(List<SpaceUser> spaceUserList) {
        if (CollUtil.isEmpty(spaceUserList)) {
            return Collections.emptyList();
        }

        // 转换
        List<SpaceUserVO> spaceUserVOList = spaceUserList.stream()
                .map(SpaceUserVO::objToVO)
                .collect(Collectors.toList());

        // 获取所有空间id和用户id
        Set<Long> spaceIdSet = spaceUserList.stream().map(SpaceUser::getSpaceId).collect(Collectors.toSet());
        Set<Long> userIdSet = spaceUserList.stream().map(SpaceUser::getUserId).collect(Collectors.toSet());

        // 批量查询用户信息和空间信息
        Map<Long, List<User>> userMap = userService.listByIds(userIdSet).stream().collect(Collectors.groupingBy(User::getId));
        Map<Long, List<Space>> spaceMap = spaceService.listByIds(spaceIdSet).stream().collect(Collectors.groupingBy(Space::getId));

        // 填充用户和空间信息
        spaceUserVOList.forEach(spaceUserVO -> {
            Long userId = spaceUserVO.getUserId();
            Long spaceId = spaceUserVO.getSpaceId();
            User user = userMap.get(userId).get(0);
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            spaceUserVO.setUserVO(userVO);
            Space space = spaceMap.get(spaceId).get(0);
            spaceUserVO.setSpaceVO(SpaceVO.objToVo(space));
        });
        return spaceUserVOList;
    }




}




